/**
 * PEYCASH 2014 - DERECHOS RESERVADOS
 */
package com.peycash.vista;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.PreDestroy;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.portlet.RenderRequest;

import org.json.JSONObject;
import org.primefaces.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.liferay.faces.util.portal.WebKeys;
import com.liferay.portal.model.User;
import com.liferay.portal.theme.ThemeDisplay;
import com.peycash.common.Constantes;
import com.peycash.common.EstatusCliente;
import com.peycash.common.TipoCliente;
import com.peycash.common.dto.ClienteDTO;
import com.peycash.common.dto.ClienteRegistroDTO;
import com.peycash.fachada.ClienteOpFachada;
import com.peycash.fachada.FachadaException;
import com.peycash.util.ClienteUtils;

/**
 * Controlador para los registros de usuarios
 * 
 * @author Jorge Amaro Coria
 * @since 1.0
 * @version 1.0
 * 
 */
@ManagedBean(name = "beanRegistro")
@ViewScoped
public class RegistroControlador extends BaseController implements
		Serializable, RegistroObserver {

	private final Logger LOGGER = LoggerFactory
			.getLogger(RegistroControlador.class);

	/**
	 * Default serial version ID
	 */
	private static final long serialVersionUID = 1L;

	@ManagedProperty("#{clienteOpFachadaImpl}")
	private ClienteOpFachada fachadaCliente;

	private List<ClienteDTO> listaClientes;
	private ClienteDTO itemSelected;
	private Integer input_idSexo;
	private String input_nombre;
	private String input_apellidoP;
	private String input_apellidoM;
	private boolean input_aceptarTerminos;
	private Date input_fechaNac;
	private String input_calleNo;
	private String input_colonia;
	private String input_municipioDelegacion;
	private int input_idEdo;
	private String input_cp;
	private boolean nuevosClientes;
	private String input_comentarios;
	private String input_identificacion;
	private int input_idEstado;
	private int input_tipoIdentificacion;
	private String input_noCel;

	public RegistroControlador() {
		ClienteUtils.getInstace().registrar(this);
	}

	@PreDestroy
	public void destroy() {
		ClienteUtils.getInstace().bajaRegistro(this);
	}

	private void initClientes() {
		listaClientes = ClienteUtils.getInstace().getListaClientes();
		updateListaClientes();
	}

	public void pooling() {
		if (nuevosClientes) {
			nuevosClientes = false;
			addNuevoClienteMensaje();
		}
	}

	public void cancelaPreregistro() {
		String noCel = itemSelected.getNoCel();
		ClienteUtils.getInstace().terminaLlamada(noCel);
	}

	public String preRegistrarCliente() {
		String noCel = itemSelected.getNoCel();
		boolean b = ClienteUtils.getInstace().isDisponible(noCel);
		if (b) {
			boolean c = ClienteUtils.getInstace().llamarCliente(noCel);
			if (c) {
				RequestContext.getCurrentInstance().execute(
						"registroDialog.show()");
			} else {
				addMessageLlamadaEnCurso();
			}
		} else {
			addMessageLlamadaEnCurso();
		}
		return "";
	}

	public void addMessageLlamadaEnCurso() {
		FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
				"Llamada en curso",
				"Otro operador se encuentra realizando esta llamada");
		RequestContext.getCurrentInstance().showMessageInDialog(message);
	}

	public String verDetalle() {
		RequestContext.getCurrentInstance().execute("detalleDialog.show()");
		return "";
	}

	public void updateListaClientes() {
		for (int i = 0; i < ClienteUtils.getInstace().getListaClientes().size(); i++) {
			ClienteDTO dto = null;
			if (ClienteUtils.getInstace().isDisponible(
					ClienteUtils.getInstace().getListaClientes().get(i)
							.getNoCel())) {
				dto = ClienteUtils.getInstace().getListaClientes().get(i);
				dto.setEstatusRegistro(Constantes.ESTATUS_REGISTRO_DISPONIBLE);
				dto.setEnabled(true);
			} else {
				dto = ClienteUtils.getInstace().getListaClientes().get(i);
				dto.setEstatusRegistro(Constantes.ESTATUS_REGISTRO_LLAMANDO);
				dto.setEnabled(false);
			}
			// listaClientes.set(i, dto);
			ClienteUtils.getInstace().setClienteEnLista(dto, i);
			listaClientes = ClienteUtils.getInstace().getListaClientes();
		}
	}

	public void populate() {
		if (CollectionUtils.isEmpty(listaClientes)) {
			initClientes();
		}
	}

	public void bajaTemporal() {
		ClienteRegistroDTO dto = new ClienteRegistroDTO();
		dto.setIdCliente(itemSelected.getIdCliente());
		dto.setComentarios(input_comentarios);
		dto.setFechaModif(new Date());
		dto.setFechaBaja(new Date());
		String mailUser = getEmailUser();
		dto.setUsuarioBd(mailUser);
		try {
			fachadaCliente.bajaTemporal(dto);
			ClienteUtils.getInstace().removeCliente(itemSelected.getNoCel());
			listaClientes = ClienteUtils.getInstace().getListaClientes();
			limpiaInputs();
			super.addInfoMessage("Se ha dado de baja temporal exitosamente");
		} catch (FachadaException e) {
			LOGGER.error("NO SE PUDO ACTUALIZAR EL REGISTRO");
			super.addErrorMessage("No se pudo actualizar el registro");
		}
	}

	public void llamarDespues() {
		ClienteRegistroDTO dto = new ClienteRegistroDTO();
		dto.setNumCel(itemSelected.getNoCel());
		dto.setFechaUltimaTrx(new Date());
		dto.setComentarios(input_comentarios);
		dto.setIdCliente(itemSelected.getIdCliente());
		String mailUser = getEmailUser();
		dto.setUsuarioBd(mailUser);
		try {
			fachadaCliente.llamarDespues(dto);
			// listaClientes.set(index, dtoCliente);
			ClienteUtils.getInstace().terminaLlamada(dto.getNumCel());
			limpiaInputs();
			super.addInfoMessage("Se ha actualizado el registro");
		} catch (FachadaException e) {
			LOGGER.error("NO SE PUDO ACTUALIZAR EL REGISTRO");
			super.addErrorMessage("No se pudo actualizar el registro");
		}
	}

	public void saveCliente() {
		boolean b = validaCamposRequeridos();
		if (!b) {
			super.addWarningMessage("Campos marcados con * son obligatorios");
			return;
		}
		try {
			long l = Long.parseLong(input_cp);
		} catch (NumberFormatException nex) {
			super.addErrorMessage("Formato de numero no valido");
			return;
		}
		if (!input_aceptarTerminos) {
			super.addWarningMessage("No ha aceptado terminos y condiciones");
			return;
		}
		String mailUser = getEmailUser();
		ClienteRegistroDTO dto = new ClienteRegistroDTO();
		dto.setNombre(input_nombre);
		dto.setApellidoPaterno(input_apellidoP);
		dto.setApellidoMaterno(input_apellidoM);
		dto.setComentarios(input_comentarios);
		dto.setIdTipoIdentificacion(input_tipoIdentificacion);
		dto.setIdentificacion(input_identificacion);
		dto.setFechaNacimiento(input_fechaNac);
		dto.setFechaAlta(new Date());
		dto.setNumCel(itemSelected.getNoCel());
		dto.setCp(input_cp);
		dto.setColonia(input_colonia);
		dto.setCalleyNo(input_calleNo);
		dto.setUsuarioBd(mailUser);
		dto.setDelegacionMunicipio(input_municipioDelegacion);
		dto.setIdEstado(input_idEstado);
		dto.setIdCliente(itemSelected.getIdCliente());
		long pkDomicilio;

		try {
			pkDomicilio = fachadaCliente.saveDomicilio(dto);
			dto.setIdDomicilio(pkDomicilio);
			fachadaCliente.saveCliente(dto);
			ClienteDTO dtoCliente = new ClienteDTO();
			dtoCliente.setIdCliente(dto.getIdCliente());
			dtoCliente.setNoCel(dto.getNumCel());
			// listaClientes.remove(dtoCliente);
			ClienteUtils.getInstace().removeClienteFromLista(dtoCliente);
			listaClientes = ClienteUtils.getInstace().getListaClientes();
			limpiaInputs();
			super.addInfoMessage("Se ha registrado al cliente exitosamente");
			RequestContext.getCurrentInstance()
					.execute("registroDialog.hide()");
		} catch (FachadaException e) {
			LOGGER.error("NO SE PUDO GUARDAR EL REGISTRO");
			super.addErrorMessage("No se pudo guardar el registro");
			return;
		}
	}

	public String getEmailUser() {
		// opcion 2
		ExternalContext extCtx = FacesContext.getCurrentInstance()
				.getExternalContext();
		ThemeDisplay themeDisplay = (ThemeDisplay) extCtx.getRequestMap().get(
				WebKeys.THEME_DISPLAY);
		User user = themeDisplay.getUser();
		String mailUser = user.getEmailAddress();
		return mailUser;
	}

	public boolean validaCamposRequeridos() {
		if (input_nombre == null || input_nombre.isEmpty()
				|| input_nombre.length() < 3) {
			return false;
		}
		if (input_apellidoP == null || input_apellidoP.isEmpty()
				|| input_apellidoP.length() < 3) {
			return false;
		}
		if (input_fechaNac == null) {
			return false;
		}
		if (input_calleNo == null || input_calleNo.isEmpty()
				|| input_calleNo.length() < 3) {
			return false;
		}
		if (input_colonia == null || input_colonia.isEmpty()
				|| input_colonia.length() < 3) {
			return false;
		}
		if (input_cp == null || input_cp.isEmpty() || input_cp.length() < 4) {
			return false;
		}
		if (input_idSexo == null || input_idSexo == 0) {
			return false;
		}
		return true;
	}

	public List<String> complete(String query) {
		try {
			List<String> list = fachadaCliente.findColoniasPorNombre(query);
			if (CollectionUtils.isEmpty(list)) {
				list = new ArrayList<String>();
			}
			return list;
		} catch (FachadaException e) {
			LOGGER.error("Error en complete:" + e.getMessage(), e);
			return new ArrayList<String>();
		}

	}

	private void limpiaInputs() {
		input_apellidoM = "";
		input_apellidoP = "";
		input_calleNo = "";
		input_colonia = "";
		input_comentarios = "";
		input_cp = "";
		input_fechaNac = null;
		input_identificacion = "";
		input_municipioDelegacion = "";
		input_noCel = "";
		input_nombre = "";
		input_nombre = "";
		input_idSexo = 0;
	}

	@Override
	public void update(String message) {
		JSONObject jsonObject = new JSONObject(message);
		String noCelEnvia = jsonObject.getString(Constantes.INPUT_NO_CEL_ENVIA);
		String id = jsonObject.getString(Constantes.INPUT_ID_CLIENTE);
		String tipo = jsonObject.getString(Constantes.INPUT_TIPO_CLIENTE);
		ClienteDTO dto = new ClienteDTO();
		dto.setEstatus(EstatusCliente.NUEVO);
		dto.setFechaUsoServicio(new Date(System.currentTimeMillis()));
		if (tipo.equals(Constantes.TIPO_CLIENTE_ENVIA)) {
			dto.setTipoCliente(TipoCliente.ENVIA);
		} else {
			dto.setTipoCliente(TipoCliente.RECIBE);
		}
		dto.setNoCel(noCelEnvia);
		dto.setIdCliente(new BigDecimal(id));
		int index = ClienteUtils.getInstace().getListaClientes().indexOf(dto);
		if (index >= 0) {
			LOGGER.info("SE HA RECIBIDO UN REGISTRO DUPLICADO ::: {} :::: ",
					dto.getNoCel());
		} else {
			// listaClientes.add(dto);
			ClienteUtils.getInstace().addCliente(dto);
			listaClientes = ClienteUtils.getInstace().getListaClientes();
			nuevosClientes = true;
			updateListaClientes();
			LOGGER.info(
					"SE HA RECIBIDO UN REGISTRO Y SE AGREGARA ::: {} :::: ",
					dto.getNoCel());
		}

		/*
		 * PushContext pushContext = PushContextFactory.getDefault()
		 * .getPushContext(); pushContext.push("/registrope", message);
		 */
	}

	public void addNuevoClienteMensaje() {
		super.addInfoMessage("Se ha agregado un nuevo cliente");
	}

	/**
	 * @return the listaClientes
	 */
	public List<ClienteDTO> getListaClientes() {
		populate();
		return listaClientes;
	}

	/**
	 * @param listaClientes
	 *            the listaClientes to set
	 */
	public void setListaClientes(List<ClienteDTO> listaClientes) {
		this.listaClientes = listaClientes;
	}

	/**
	 * @return the itemSelected
	 */
	public ClienteDTO getItemSelected() {
		return itemSelected;
	}

	/**
	 * @param itemSelected
	 *            the itemSelected to set
	 */
	public void setItemSelected(ClienteDTO itemSelected) {
		this.itemSelected = itemSelected;
	}

	/**
	 * @return the idSexo
	 */
	public Integer getInput_idSexo() {
		return input_idSexo;
	}

	/**
	 * @param idSexo
	 *            the idSexo to set
	 */
	public void setInput_idSexo(Integer input_idSexo) {
		this.input_idSexo = input_idSexo;
	}

	/**
	 * @return the input_nombre
	 */
	public String getInput_nombre() {
		return input_nombre;
	}

	/**
	 * @param input_nombre
	 *            the input_nombre to set
	 */
	public void setInput_nombre(String input_nombre) {
		this.input_nombre = input_nombre;
	}

	/**
	 * @return the input_apellidoP
	 */
	public String getInput_apellidoP() {
		return input_apellidoP;
	}

	/**
	 * @param input_apellidoP
	 *            the input_apellidoP to set
	 */
	public void setInput_apellidoP(String input_apellidoP) {
		this.input_apellidoP = input_apellidoP;
	}

	/**
	 * @return the input_apellidoM
	 */
	public String getInput_apellidoM() {
		return input_apellidoM;
	}

	/**
	 * @param input_apellidoM
	 *            the input_apellidoM to set
	 */
	public void setInput_apellidoM(String input_apellidoM) {
		this.input_apellidoM = input_apellidoM;
	}

	/**
	 * @return the input_aceptarTerminos
	 */
	public boolean isInput_aceptarTerminos() {
		return input_aceptarTerminos;
	}

	/**
	 * @param input_aceptarTerminos
	 *            the input_aceptarTerminos to set
	 */
	public void setInput_aceptarTerminos(boolean input_aceptarTerminos) {
		this.input_aceptarTerminos = input_aceptarTerminos;
	}

	/**
	 * @return the input_fechaNac
	 */
	public Date getInput_fechaNac() {
		return input_fechaNac;
	}

	/**
	 * @param input_fechaNac
	 *            the input_fechaNac to set
	 */
	public void setInput_fechaNac(Date input_fechaNac) {
		this.input_fechaNac = input_fechaNac;
	}

	/**
	 * @return the input_calleNo
	 */
	public String getInput_calleNo() {
		return input_calleNo;
	}

	/**
	 * @param input_calleNo
	 *            the input_calleNo to set
	 */
	public void setInput_calleNo(String input_calleNo) {
		this.input_calleNo = input_calleNo;
	}

	/**
	 * @return the input_colonia
	 */
	public String getInput_colonia() {
		return input_colonia;
	}

	/**
	 * @param input_colonia
	 *            the input_colonia to set
	 */
	public void setInput_colonia(String input_colonia) {
		this.input_colonia = input_colonia;
	}

	/**
	 * @return the input_municipioDelegacion
	 */
	public String getInput_municipioDelegacion() {
		return input_municipioDelegacion;
	}

	/**
	 * @param input_municipioDelegacion
	 *            the input_municipioDelegacion to set
	 */
	public void setInput_municipioDelegacion(String input_municipioDelegacion) {
		this.input_municipioDelegacion = input_municipioDelegacion;
	}

	/**
	 * @return the input_idEdo
	 */
	public int getInput_idEdo() {
		return input_idEdo;
	}

	/**
	 * @param input_idEdo
	 *            the input_idEdo to set
	 */
	public void setInput_idEdo(int input_idEdo) {
		this.input_idEdo = input_idEdo;
	}

	/**
	 * @return the input_cp
	 */
	public String getInput_cp() {
		return input_cp;
	}

	/**
	 * @param input_cp
	 *            the input_cp to set
	 */
	public void setInput_cp(String input_cp) {
		this.input_cp = input_cp;
	}

	public ClienteOpFachada getFachadaCliente() {
		return fachadaCliente;
	}

	public void setFachadaCliente(ClienteOpFachada fachadaCliente) {
		this.fachadaCliente = fachadaCliente;
	}

	public boolean isNuevosClientes() {
		return nuevosClientes;
	}

	public void setNuevosClientes(boolean nuevosClientes) {
		this.nuevosClientes = nuevosClientes;
	}

	/**
	 * @return the input_comentarios
	 */
	public String getInput_comentarios() {
		return input_comentarios;
	}

	/**
	 * @param input_comentarios
	 *            the input_comentarios to set
	 */
	public void setInput_comentarios(String input_comentarios) {
		this.input_comentarios = input_comentarios;
	}

	/**
	 * @return the input_identificacion
	 */
	public String getInput_identificacion() {
		return input_identificacion;
	}

	/**
	 * @param input_identificacion
	 *            the input_identificacion to set
	 */
	public void setInput_identificacion(String input_identificacion) {
		this.input_identificacion = input_identificacion;
	}

	/**
	 * @return the input_idEstado
	 */
	public int getInput_idEstado() {
		return input_idEstado;
	}

	/**
	 * @param input_idEstado
	 *            the input_idEstado to set
	 */
	public void setInput_idEstado(int input_idEstado) {
		this.input_idEstado = input_idEstado;
	}

	/**
	 * @return the input_tipoIdentificacion
	 */
	public int getInput_tipoIdentificacion() {
		return input_tipoIdentificacion;
	}

	/**
	 * @param input_tipoIdentificacion
	 *            the input_tipoIdentificacion to set
	 */
	public void setInput_tipoIdentificacion(int input_tipoIdentificacion) {
		this.input_tipoIdentificacion = input_tipoIdentificacion;
	}

	@Override
	public void clienteOcupado(String noCel) {
		for (int i = 0; i < ClienteUtils.getInstace().getListaClientes().size(); i++) {
			if (ClienteUtils.getInstace().getListaClientes().get(i).getNoCel()
					.equals(noCel)) {
				ClienteDTO dto = ClienteUtils.getInstace().getListaClientes()
						.get(i);
				dto.setEstatusRegistro(Constantes.ESTATUS_REGISTRO_LLAMANDO);
				// listaClientes.set(i, dto);
				ClienteUtils.getInstace().setClienteEnLista(dto, i);
				listaClientes = ClienteUtils.getInstace().getListaClientes();
			}
		}
	}

	@Override
	public void terminaLlamada(String noCel) {
		for (int i = 0; i < ClienteUtils.getInstace().getListaClientes().size(); i++) {
			if (ClienteUtils.getInstace().getListaClientes().get(i).getNoCel()
					.equals(noCel)) {
				ClienteDTO dto = ClienteUtils.getInstace().getListaClientes()
						.get(i);
				dto.setEstatusRegistro(Constantes.ESTATUS_REGISTRO_DISPONIBLE);
				dto.setFechaUltimaLlamada(new Date());
				// listaClientes.set(i, dto);
				ClienteUtils.getInstace().setClienteEnLista(dto, i);
				listaClientes = ClienteUtils.getInstace().getListaClientes();
			}
		}
	}

	@Override
	public void removeCliente(String noCel) {
		for (int i = 0; i < ClienteUtils.getInstace().getListaClientes().size(); i++) {
			if (ClienteUtils.getInstace().getListaClientes().get(i).getNoCel()
					.equals(noCel)) {
				// listaClientes.remove(i);
				ClienteUtils.getInstace().removeClienteFromLista(i);
				listaClientes = ClienteUtils.getInstace().getListaClientes();
			}
		}
	}

	/**
	 * @return the input_noCel
	 */
	public String getInput_noCel() {
		return input_noCel;
	}

	/**
	 * @param input_noCel
	 *            the input_noCel to set
	 */
	public void setInput_noCel(String input_noCel) {
		this.input_noCel = input_noCel;
	}

}
